home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / term / term_47a_pch.lha / Source / gtlayout-38.3 / LTP_LayoutGroup.c < prev    next >
C/C++ Source or Header  |  1996-11-12  |  21KB  |  834 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1996 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. #ifdef NOT_FUNCTIONAL
  15.  
  16.     /* LTP_ShuffleGroup(LayoutHandle *Handle,ObjectNode *Group):
  17.      *
  18.      *    Propagate size relationships between groups on the
  19.      *    same tree level.
  20.      *
  21.      *    On second thought, this was not such a good idea after
  22.      *    all. I'll redo the stuff when I find the time.
  23.      */
  24.  
  25. VOID
  26. LTP_ShuffleGroup(LayoutHandle *Handle,ObjectNode *Group)
  27. {
  28.     if(!Handle->Failed)
  29.     {
  30.         ObjectNode    *Node;
  31.         LONG         WidthCount        = 0,
  32.                      HeightCount    = 0;
  33.  
  34.             // First step: count the number of nodes which should share
  35.             //             the sizes with other groups. Validate the
  36.             //             group relationships on the fly, cancelling
  37.             //             links which point to nonexistant objects.
  38.  
  39.         SCANGROUP(Group,Node)
  40.         {
  41.             if(Node->Type == GROUP_KIND)
  42.             {
  43.                     // Use the size of another group?
  44.  
  45.                 if(Node->Special.Group.UseWidth != -1)
  46.                 {
  47.                     ObjectNode    *Other;
  48.                     BOOL         GotIt = FALSE;
  49.  
  50.                         // Scan the list for the group in question...
  51.  
  52.                     SCANGROUP(Group,Other)
  53.                     {
  54.                             // Is it this one?
  55.  
  56.                         if(Other != Node && Node->ID == Node->Special.Group.UseWidth)
  57.                         {
  58.                             GotIt = TRUE;
  59.                             break;
  60.                         }
  61.                     }
  62.  
  63.                         // If this one is valid, update the counter,
  64.                         // else cancel the link
  65.  
  66.                     if(GotIt)
  67.                         WidthCount++;
  68.                     else
  69.                         Node->Special.Group.UseWidth = -1;
  70.                 }
  71.  
  72.                 if(Node->Special.Group.UseHeight != -1)
  73.                 {
  74.                     ObjectNode    *Other;
  75.                     BOOL         GotIt = FALSE;
  76.  
  77.                     SCANGROUP(Group,Other)
  78.                     {
  79.                         if(Other != Node && Node->ID == Node->Special.Group.UseHeight)
  80.                         {
  81.                             GotIt = TRUE;
  82.                             break;
  83.                         }
  84.                     }
  85.  
  86.                     if(GotIt)
  87.                         HeightCount++;
  88.                     else
  89.                         Node->Special.Group.UseHeight = -1;
  90.                 }
  91.             }
  92.         }
  93.  
  94.             // Second step: If any valid relationships were found,
  95.             //              propagate the sizes.
  96.  
  97.         if(WidthCount || HeightCount)
  98.         {
  99.             ObjectNode **Table;
  100.             LONG Total = sizeof(ObjectNode *) * MAX(WidthCount,HeightCount);
  101.  
  102.                 // Some temporary storage for keeping the nodes
  103.  
  104.             if(Table = (ObjectNode **)LTP_Alloc(Handle,Total))
  105.             {
  106.                 LONG Handled = 0,Collected = 0,Wanted = -1,i,MaxWidth,MaxHeight;
  107.  
  108.                     // Loop until all width relationships are resolved.
  109.  
  110.                 while(Handled < WidthCount)
  111.                 {
  112.                     Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
  113.  
  114.                         // Scan until we hit the end
  115.  
  116.                     while(Node->Node.mln_Succ)
  117.                     {
  118.                             // Is this a group we didn't check yet, but would
  119.                             // need to take a look at?
  120.  
  121.                         if(Node->Type == GROUP_KIND && Node->Special.Group.UseWidth != -1 && !(Node->Special.Group.MiscFlags & GROUPF_WidthDone))
  122.                         {
  123.                                 // Should we keep this one?
  124.  
  125.                             if(Wanted == -1 || Node->ID == Wanted)
  126.                             {
  127.                                     // Keep this one
  128.  
  129.                                 Table[Collected++] = Node;
  130.  
  131.                                     // Don't check this one again
  132.  
  133.                                 Node->Special.Group.MiscFlags |= GROUPF_WidthDone;
  134.  
  135.                                     // We'll search for this one unless
  136.                                     // it points nowhere
  137.  
  138.                                 if((Wanted = Node->Special.Group.UseWidth) == -1)
  139.                                     break;
  140.                                 else    // Start again...
  141.                                     Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
  142.                             }
  143.                             else
  144.                                 Node = (ObjectNode *)Node->Node.mln_Succ;
  145.                         }
  146.                         else
  147.                             Node = (ObjectNode *)Node->Node.mln_Succ;
  148.                     }
  149.  
  150.                         // Determine maximum width of objects
  151.  
  152.                     for(i = MaxWidth = 0 ; i < Collected ; i++)
  153.                     {
  154.                         if(Table[i]->Width > MaxWidth)
  155.                             MaxWidth = Table[i]->Width;
  156.                     }
  157.  
  158.                         // Make all objects as large as the largest object
  159.  
  160.                     for(i = 0 ; i < Collected ; i++)
  161.                         Table[i]->Width = MaxWidth;
  162.  
  163.                         // Update the counter
  164.  
  165.                     Handled += Collected;
  166.  
  167.                         // Scan until all references are resolved
  168.  
  169.                     Collected = 0;
  170.                 }
  171.  
  172.                 Handled = 0;
  173.  
  174.                 while(Handled < HeightCount)
  175.                 {
  176.                     Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
  177.  
  178.                     while(Node->Node.mln_Succ)
  179.                     {
  180.                         if(Node->Type == GROUP_KIND && Node->Special.Group.UseHeight != -1 && !(Node->Special.Group.MiscFlags & GROUPF_HeightDone))
  181.                         {
  182.                             if(Wanted == -1 || Node->ID == Wanted)
  183.                             {
  184.                                 Table[Collected++] = Node;
  185.  
  186.                                 Node->Special.Group.MiscFlags |= GROUPF_HeightDone;
  187.  
  188.                                 if((Wanted = Node->Special.Group.UseHeight) == -1)
  189.                                     break;
  190.                                 else
  191.                                     Node = (ObjectNode *)Group->Special.Group.ObjectList.mlh_Head;
  192.                             }
  193.                             else
  194.                                 Node = (ObjectNode *)Node->Node.mln_Succ;
  195.                         }
  196.                         else
  197.                             Node = (ObjectNode *)Node->Node.mln_Succ;
  198.                     }
  199.  
  200.                     for(i = MaxHeight = 0 ; i < Collected ; i++)
  201.                     {
  202.                         if(Table[i]->Height > MaxHeight)
  203.                             MaxHeight = Table[i]->Height;
  204.                     }
  205.  
  206.                     for(i = 0 ; i < Collected ; i++)
  207.                         Table[i]->Height = MaxHeight;
  208.  
  209.                     Handled += Collected;
  210.  
  211.                     Collected = 0;
  212.                 }
  213.  
  214.                 LTP_Free(Handle,Table,Total);
  215.             }
  216.         }
  217.  
  218.             // Step three: do the just the same to all the other groups
  219.             //             (tail recursion).
  220.  
  221.         SCANGROUP(Group,Node)
  222.         {
  223.             if(Node->Type == GROUP_KIND)
  224.                 LTP_ShuffleGroup(Handle,Node);
  225.         }
  226.     }
  227. }
  228. #endif    // NOT_FUNCTIONAL
  229.  
  230. VOID
  231. LTP_LayoutGroup(LayoutHandle *Handle,ObjectNode *Group)
  232. {
  233.     if(!Handle->Failed)
  234.     {
  235.         ObjectNode    *Node;
  236.         ObjectNode    *ReturnKey;
  237.         ObjectNode    *EscKey;
  238.         ObjectNode    *CursorKey;
  239.         ObjectNode    *TabKey;
  240.         ObjectNode    *ActiveString;
  241.         LONG         Left;
  242.         LONG         Top;
  243.         LONG         Width;
  244.         LONG         Height;
  245.         LONG         MaxWidth;
  246.         LONG         MaxHeight;
  247.         BOOL         DefaultCorrection;
  248.  
  249.         Left                = 0;
  250.         Top                    = 0;
  251.         ReturnKey            = NULL;
  252.         EscKey                = NULL;
  253.         CursorKey            = NULL;
  254.         TabKey                = NULL;
  255.         ActiveString        = NULL;
  256.         DefaultCorrection    = FALSE;
  257.         MaxWidth            = 0;
  258.         MaxHeight            = 0;
  259.  
  260.         SCANGROUP(Group,Node)
  261.         {
  262.             LTP_DetermineSize(Handle,Node);
  263.  
  264.             switch(Node->Type)
  265.             {
  266.                 case BUTTON_KIND:
  267.  
  268.                     if(Node->Special.Button.ReturnKey)
  269.                         ReturnKey = Node;
  270.                     else
  271.                     {
  272.                         if(Node->Special.Button.EscKey)
  273.                             EscKey = Node;
  274.                     }
  275.  
  276.                     DefaultCorrection |= Node->Special.Button.DefaultCorrection;
  277.  
  278.                     break;
  279.  
  280.                 case CYCLE_KIND:
  281.  
  282.                     if(Node->Special.Cycle.TabKey)
  283.                         TabKey = Node;
  284.  
  285.                     break;
  286.  
  287. #if defined(DO_POPUP_KIND) && defined(DO_BOOPSI_KIND)
  288.                 case POPUP_KIND:
  289.  
  290.                     if(Node->Special.Popup.TabKey)
  291.                         TabKey = Node;
  292.  
  293.                     break;
  294. #endif
  295.  
  296. #if defined(DO_TAB_KIND) && defined(DO_BOOPSI_KIND)
  297.                 case TAB_KIND:
  298.  
  299.                     if(Node->Special.Tab.TabKey)
  300.                         TabKey = Node;
  301.  
  302.                     break;
  303. #endif
  304.                 case MX_KIND:
  305.  
  306.                     if(Node->Special.Radio.TabKey)
  307.                         TabKey = Node;
  308.  
  309.                     break;
  310.  
  311.                 case PASSWORD_KIND:
  312.                 case STRING_KIND:
  313.                 case FRACTION_KIND:
  314.  
  315.                     if(Node->Special.String.Activate)
  316.                         ActiveString = Node;
  317.  
  318.                     break;
  319.  
  320.                 case INTEGER_KIND:
  321.  
  322.                     if(Node->Special.Integer.Activate)
  323.                         ActiveString = Node;
  324.  
  325.                     break;
  326.  
  327.                 case LISTVIEW_KIND:
  328.  
  329.                     if(Node->Special.List.CursorKey)
  330.                         CursorKey = Node;
  331.  
  332.                     break;
  333.             }
  334.  
  335.             if(Node->Width > MaxWidth)
  336.                 MaxWidth = Node->Width;
  337.  
  338.             if(Node->Height > MaxHeight)
  339.                 MaxHeight = Node->Height;
  340.         }
  341.  
  342.         if(ReturnKey || DefaultCorrection)
  343.         {
  344.             SCANGROUP(Group,Node)
  345.             {
  346. #ifdef OLD_STYLE_DEFAULT_KEY
  347.                 Node->GroupIndent = TRUE;
  348.  
  349.                 Node->Width        += 4 + 4;
  350.                 Node->Height    += 2 + 2;
  351. #else
  352.                 Node->Width        += 1 + 1;
  353.                 Node->Height    += 1 + 1;
  354. #endif
  355.                 if(Node->Width > MaxWidth)
  356.                     MaxWidth = Node->Width;
  357.  
  358.                 if(Node->Height > MaxHeight)
  359.                     MaxHeight = Node->Height;
  360.             }
  361.         }
  362.  
  363.         if(Group->Special.Group.SameSize)
  364.         {
  365.             SCANGROUP(Group,Node)
  366.             {
  367.                 if(Node->Width < MaxWidth && Node->Type != YBAR_KIND && Node->Type != CHECKBOX_KIND)
  368.                 {
  369.                     if(Node->Type == GROUP_KIND && !Node->Special.Group.NoIndent)
  370.                         Node->Special.Group.ExtraLeft += (MaxWidth - Node->Width) / 2;
  371.  
  372.                     Node->Width = MaxWidth;
  373.                 }
  374.  
  375.                 if(Node->Height < MaxHeight && Node->Type != XBAR_KIND && Node->Type != CHECKBOX_KIND)
  376.                 {
  377.                     if(Node->Type == GROUP_KIND && !Node->Special.Group.NoIndent)
  378.                         Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2;
  379.  
  380.                     Node->Height = MaxHeight;
  381.                 }
  382.             }
  383.         }
  384.  
  385.         if(Group->Special.Group.Horizontal)
  386.         {
  387.             LONG x,y,w,MaxTop = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;
  388.  
  389.             if(Group->Node.mln_Pred->mln_Pred && Group->Special.Group.LastAttributes)
  390.             {
  391.                 ObjectNode *LastGroup = (ObjectNode *)Group->Node.mln_Pred;
  392.  
  393.                 MaxTop        = LastGroup->Special.Group.MaxOffset;
  394.                 MaxHeight    = LastGroup->Special.Group.MaxSize;
  395.             }
  396.  
  397.             SCANGROUP(Group,Node)
  398.             {
  399.                 if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
  400.                 {
  401.                     if(!Group->Special.Group.Paging && Count++)
  402.                     {
  403.                         if(Node->ExtraSpace > 0)
  404.                             x = Left + Node->ExtraSpace * Handle->InterWidth;
  405.                         else
  406.                         {
  407.                             if(Node->ExtraSpace < 0)
  408.                                 x = Left - Node->ExtraSpace;
  409.                             else
  410.                                 x = Left + Handle->InterWidth;
  411.                         }
  412.                     }
  413.                     else
  414.                         x = Left;
  415.  
  416.                     y = Top;
  417.                     w = Node->Width;
  418.  
  419.                     switch(Node->LabelPlace)
  420.                     {
  421.                         case PLACE_LEFT:
  422.  
  423.                             if(Node->Type == MX_KIND)
  424.                             {
  425.                                 x += Node->Special.Radio.LabelWidth + INTERWIDTH;
  426.  
  427.                                 if(Node->Label)
  428.                                 {
  429.                                     if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
  430.                                         x += Node->LabelWidth + INTERWIDTH;
  431.                                     else
  432.                                         w += INTERWIDTH + Node->LabelWidth;
  433.                                 }
  434.                             }
  435.                             else
  436.                             {
  437.                                 if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  438.                                     x += Node->LabelWidth + INTERWIDTH;
  439.                             }
  440.  
  441.                             break;
  442.  
  443.                         case PLACE_RIGHT:
  444.  
  445.                             if(Node->Type == MX_KIND)
  446.                             {
  447.                                 w += INTERWIDTH + Node->Special.Radio.LabelWidth;
  448.  
  449.                                 if(Node->Label)
  450.                                 {
  451.                                     if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
  452.                                         x += Node->LabelWidth + INTERWIDTH;
  453.                                     else
  454.                                         w += INTERWIDTH + Node->LabelWidth;
  455.                                 }
  456.                             }
  457.                             else
  458.                             {
  459.                                 if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  460.                                     w += INTERWIDTH + Node->LabelWidth;
  461.                             }
  462.  
  463.                             break;
  464.  
  465.                         case PLACE_ABOVE:
  466.  
  467.                             if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  468.                             {
  469.                                 if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
  470.                                     y += Node->Special.List.FixedGlyphHeight + INTERHEIGHT;
  471.                                 else
  472.                                     y += Handle->GlyphHeight + INTERHEIGHT;
  473.                             }
  474.  
  475.                             break;
  476.                     }
  477.  
  478.                     if(Node->Type == SLIDER_KIND)
  479.                     {
  480.                         if(Node->Special.Slider.LevelPlace == PLACETEXT_RIGHT && Node->Special.Slider.LevelFormat)
  481.                             w += INTERWIDTH + Node->Special.Slider.LevelWidth;
  482.  
  483.                         if(Node->Special.Slider.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT && Node->Special.Slider.LevelFormat)
  484.                             x += INTERWIDTH + Node->Special.Slider.LevelWidth;
  485.                     }
  486.  
  487. #ifdef DO_LEVEL_KIND
  488.                     if(Node->Type == LEVEL_KIND)
  489.                     {
  490.                         if(Node->Special.Level.LevelPlace == PLACETEXT_RIGHT)
  491.                             w += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
  492.  
  493.                         if(Node->Special.Level.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT)
  494.                             x += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
  495.                     }
  496. #endif    /* DO_LEVEL_KIND */
  497.  
  498.                     if(Node->Type == LISTVIEW_KIND && Node->Special.List.ExtraLabelWidth)
  499.                         x += Node->Special.List.ExtraLabelWidth + INTERWIDTH;
  500.  
  501.                     if(y > MaxTop)
  502.                         MaxTop = y;
  503.  
  504.                     if(Node->Height > MaxHeight)
  505.                         MaxHeight = Node->Height;
  506.  
  507.                     if(Node->LabelPlace == PLACE_BELOW && Node->Label)
  508.                     {
  509.                         LONG Height;
  510.  
  511.                         if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
  512.                             Height = Node->Height + INTERHEIGHT + Node->Special.List.FixedGlyphHeight;
  513.                         else
  514.                             Height = Node->Height + INTERHEIGHT + Handle->GlyphHeight;
  515.  
  516.                         if(Height > MaxHeight)
  517.                             MaxHeight = Height;
  518.                     }
  519.                     else
  520.                     {
  521.                         if(Node->Height > MaxHeight)
  522.                             MaxHeight = Node->Height;
  523.                     }
  524.  
  525.                     if(x + w > MaxWidth)
  526.                         MaxWidth = x+w;
  527.  
  528.                     Node->Left = x;
  529.  
  530.                     if(!Group->Special.Group.Paging)
  531.                         Left = x + w;
  532.                 }
  533.             }
  534.  
  535.             SCANGROUP(Group,Node)
  536.             {
  537.                 if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
  538.                 {
  539.                     Node->Top = MaxTop;
  540.  
  541.                     if(Node->Height < MaxHeight)
  542.                     {
  543. #ifdef DO_BOOPSI_KIND
  544.                         if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || Node->Type == LISTVIEW_KIND || (Node->Type == BOOPSI_KIND && !Node->Special.BOOPSI.ExactHeight))
  545. #else
  546.                         if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || Node->Type == LISTVIEW_KIND || Node->Type == BOOPSI_KIND)
  547. #endif    /* DO_BOOPSI_KIND */
  548.                             Node->Height = MaxHeight;
  549.                         else
  550.                         {
  551.                             if(Node->Type == GROUP_KIND)
  552.                             {
  553.                                 if(Node->Special.Group.Spread)
  554.                                     LTP_Spread(Handle,Node,Node->Width,MaxHeight);
  555.                                 else
  556.                                 {
  557.                                     if(!Node->Special.Group.NoIndent)
  558.                                         Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2; /* !FIX! */
  559.                                 }
  560.  
  561.                                 Node->Height = MaxHeight;
  562.                             }
  563.                         }
  564.                     }
  565.                 }
  566.             }
  567.  
  568.             Group->Special.Group.MaxOffset = MaxTop;
  569.             Group->Special.Group.MaxSize   = MaxHeight;
  570.  
  571.             if(Group->Special.Group.Paging)
  572.                 Width = MaxWidth;
  573.             else
  574.                 Width = Left;
  575.  
  576.             Height = MaxTop + MaxHeight;
  577.         }
  578.         else
  579.         {
  580.             LONG x,y,w,MaxLeft = 0,MaxWidth = 0,MaxHeight = 0,Count = 0;
  581.  
  582.             if(Group->Node.mln_Pred->mln_Pred && Group->Special.Group.LastAttributes)
  583.             {
  584.                 ObjectNode *LastGroup = (ObjectNode *)Group->Node.mln_Pred;
  585.  
  586.                 MaxLeft     = LastGroup->Special.Group.MaxOffset;
  587.                 MaxWidth    = LastGroup->Special.Group.MaxSize;
  588.             }
  589.  
  590.             SCANGROUP(Group,Node)
  591.             {
  592.                 if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
  593.                 {
  594.                     if(!Group->Special.Group.Paging && Count++)
  595.                     {
  596.                         if(Node->ExtraSpace > 0)
  597.                             y = Top + Node->ExtraSpace * Handle->InterHeight;
  598.                         else
  599.                         {
  600.                             if(Node->ExtraSpace < 0)
  601.                                 y = Top - Node->ExtraSpace;
  602.                             else
  603.                                 y = Top + Handle->InterHeight;
  604.                         }
  605.                     }
  606.                     else
  607.                         y = Top;
  608.  
  609.                     w = Node->Width;
  610.                     x = Left;
  611.  
  612.                     switch(Node->LabelPlace)
  613.                     {
  614.                         case PLACE_LEFT:
  615.  
  616.                             if(Node->Type == MX_KIND)
  617.                             {
  618.                                 x += Node->Special.Radio.LabelWidth + INTERWIDTH;
  619.  
  620.                                 if(Node->Label)
  621.                                 {
  622.                                     if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
  623.                                         x += Node->LabelWidth + INTERWIDTH;
  624.                                 }
  625.                             }
  626.                             else
  627.                             {
  628.                                 if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  629.                                     x += Node->LabelWidth + INTERWIDTH;
  630.                             }
  631.  
  632.                             break;
  633.  
  634.                         case PLACE_RIGHT:
  635.  
  636.                             if(Node->Type == MX_KIND)
  637.                             {
  638.                                 w += INTERWIDTH + Node->Special.Radio.LabelWidth;
  639.  
  640.                                 if(Node->Label)
  641.                                 {
  642.                                     if(Node->Special.Radio.TitlePlace == PLACETEXT_LEFT)
  643.                                         x += Node->LabelWidth + INTERWIDTH;
  644.                                     else
  645.                                         w += INTERWIDTH + Node->LabelWidth;
  646.                                 }
  647.                             }
  648.                             else
  649.                             {
  650.                                 if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  651.                                     w += INTERWIDTH + Node->LabelWidth;
  652.                             }
  653.  
  654.                             break;
  655.  
  656.                         case PLACE_ABOVE:
  657.  
  658.                             if(Node->Label || (Node->Type == BOX_KIND && Node->Special.Box.Labels))
  659.                             {
  660.                                 if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
  661.                                     y += Node->Special.List.FixedGlyphHeight + INTERHEIGHT;
  662.                                 else
  663.                                     y += Handle->GlyphHeight + INTERHEIGHT;
  664.                             }
  665.  
  666.                             break;
  667.                     }
  668.  
  669.                     if(Node->Type == SLIDER_KIND)
  670.                     {
  671.                         if(Node->Special.Slider.LevelPlace == PLACETEXT_RIGHT && Node->Special.Slider.LevelFormat)
  672.                             w += INTERWIDTH + Node->Special.Slider.LevelWidth;
  673.  
  674.                         if(Node->Special.Slider.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT && Node->Special.Slider.LevelFormat)
  675.                             x += INTERWIDTH + Node->Special.Slider.LevelWidth;
  676.                     }
  677.  
  678. #ifdef DO_LEVEL_KIND
  679.                     if(Node->Type == LEVEL_KIND)
  680.                     {
  681.                         if(Node->Special.Level.LevelPlace == PLACETEXT_RIGHT)
  682.                             w += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
  683.  
  684.                         if(Node->Special.Level.LevelPlace == PLACETEXT_LEFT && Node->LabelPlace != PLACE_LEFT)
  685.                             x += INTERWIDTH + Node->Special.Level.MaxLevelWidth;
  686.                     }
  687. #endif    /* DO_LEVEL_KIND */
  688.                     if(Node->Type == LISTVIEW_KIND && Node->Special.List.ExtraLabelWidth)
  689.                         x += Node->Special.List.ExtraLabelWidth + INTERWIDTH;
  690.  
  691.                     if(x > MaxLeft)
  692.                         MaxLeft = x;
  693.  
  694.                     if(w > MaxWidth)
  695.                         MaxWidth = w;
  696.  
  697.                     if(y + Node->Height > MaxHeight)
  698.                         MaxHeight = y + Node->Height;
  699.  
  700.                     Node->Top = y;
  701.  
  702.                     if(!Group->Special.Group.Paging)
  703.                         Top = y + Node->Height;
  704.  
  705.                     if(Node->LabelPlace == PLACE_BELOW && Node->Label)
  706.                     {
  707.                         if(Node->Type == LISTVIEW_KIND && Node->Special.List.TextAttr && Node->Special.List.FlushLabelLeft)
  708.                             Top += INTERHEIGHT + Node->Special.List.FixedGlyphHeight;
  709.                         else
  710.                             Top += INTERHEIGHT + Handle->GlyphHeight;
  711.                     }
  712.                 }
  713.             }
  714.  
  715.             SCANGROUP(Group,Node)
  716.             {
  717.                 if(!LIKE_STRING_KIND(Node) || Node->Special.String.LinkID == -1)
  718.                 {
  719.                     Node->Left = MaxLeft;
  720.  
  721.                     if(Node->Type == GROUP_KIND && Group->Special.Group.Paging && !Node->Special.Group.NoIndent)
  722.                         Node->Special.Group.ExtraTop += (MaxHeight - Node->Height) / 2;
  723.  
  724.                     if(Node->Width < MaxWidth)
  725.                     {
  726.                         if(Node->Type == GROUP_KIND)
  727.                         {
  728.                             if(Node->Special.Group.Spread)
  729.                                 LTP_Spread(Handle,Node,MaxWidth,Node->Height);
  730.                             else
  731.                             {
  732.                                 if(!Node->Special.Group.NoIndent)
  733.                                     Node->Special.Group.ExtraLeft += (MaxWidth - Node->Width) / 2;
  734.                             }
  735.  
  736.                             Node->Width = MaxWidth;
  737.                         }
  738.                         else
  739.                         {
  740. #ifdef DO_BOOPSI_KIND
  741.                             if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || (Node->Type == LISTVIEW_KIND && !Node->Special.List.LockSize) || (Node->Type == TEXT_KIND && !Node->Special.Text.LockSize) || Node->Type == GAUGE_KIND || Node->Type == NUMBER_KIND || Node->Type == CYCLE_KIND || LIKE_STRING_KIND(Node) || Node->Type == INTEGER_KIND || Node->Type == BUTTON_KIND || Node->Type == BOX_KIND || Node->Type == SCROLLER_KIND || Node->Type == SLIDER_KIND || Node->Type == LEVEL_KIND || (Node->Type == BOOPSI_KIND && !Node->Special.BOOPSI.ExactWidth) || Node->Type == POPUP_KIND || Node->Type == TAB_KIND || Node->Type == BLANK_KIND)
  742. #else
  743.                             if((Node->Type == PALETTE_KIND && !Node->Special.Palette.UsePicker) || (Node->Type == LISTVIEW_KIND && !Node->Special.List.LockSize) || (Node->Type == TEXT_KIND && !Node->Special.Text.LockSize) || Node->Type == GAUGE_KIND || Node->Type == NUMBER_KIND || Node->Type == CYCLE_KIND || LIKE_STRING_KIND(Node) || Node->Type == INTEGER_KIND || Node->Type == BUTTON_KIND || Node->Type == BOX_KIND || Node->Type == SCROLLER_KIND || Node->Type == SLIDER_KIND || Node->Type == LEVEL_KIND || Node->Type == BLANK_KIND)
  744. #endif    /* DO_BOOPSI_KIND */
  745.                             {
  746.                                 if(Node->Label && Node->LabelPlace == PLACE_RIGHT)
  747.                                     Node->Width = MaxWidth - (INTERWIDTH + Node->LabelWidth);
  748.                                 else
  749.                                     Node->Width = MaxWidth;
  750.                             }
  751.                         }
  752.                     }
  753.                 }
  754.             }
  755.  
  756.             Group->Special.Group.MaxOffset  = MaxLeft;
  757.             Group->Special.Group.MaxSize    = MaxWidth;
  758.  
  759.             if(Group->Special.Group.Paging)
  760.                 Height = MaxHeight;
  761.             else
  762.                 Height = Top;
  763.  
  764.             Width = MaxLeft + MaxWidth;
  765.         }
  766.  
  767.         Group->Left        = 0;
  768.         Group->Top        = 0;
  769.         Group->Width    = Width;
  770.         Group->Height    = Height;
  771.  
  772.         if(Group->Label || Group->Special.Group.Frame || Group->Special.Group.FrameType != FRAMETYPE_None)
  773.         {
  774.             if(Group->Label)
  775.             {
  776.                 Group->LabelWidth = LT_LabelWidth(Handle,Group->Label) + 2 * Handle->GlyphWidth;
  777.  
  778.                 Group->Height += Handle->GlyphHeight + 2 * Handle->InterHeight + 3;
  779.             }
  780.             else
  781.             {
  782.                 Group->LabelWidth = 0;
  783.  
  784.                 Group->Height += 2 + 2 * Handle->InterHeight + 3;
  785.             }
  786.  
  787.             if(Group->LabelWidth > Group->Width)
  788.             {
  789.                 if(!Node->Special.Group.NoIndent)
  790.                     Group->Special.Group.ExtraLeft += (Group->LabelWidth - Group->Width) / 2;
  791.  
  792.                 Group->Width = Group->LabelWidth;
  793.             }
  794.             else
  795.             {
  796.                 if(Group->Special.Group.FrameType == FRAMETYPE_Tab)
  797.                 {
  798.                     Group->Special.Group.ExtraLeft += Handle->GlyphWidth;
  799.                     Group->Width += 2 * Handle->GlyphWidth;
  800.                 }
  801.             }
  802.  
  803.             Group->Width += 2 * (Handle->GlyphWidth + Handle->InterWidth) + 8;
  804.         }
  805.  
  806.         if(Group->Special.Group.IndentX)
  807.         {
  808.             Group->Width                    += 2 * Handle->InterWidth;
  809.             Group->Special.Group.ExtraLeft    += Handle->InterWidth;
  810.         }
  811.  
  812.         if(Group->Special.Group.IndentY)
  813.         {
  814.             Group->Height                    += 2 * Handle->InterHeight;
  815.             Group->Special.Group.ExtraTop    += Handle->InterHeight;
  816.         }
  817.  
  818.         if(ReturnKey)
  819.             Handle->ReturnKey = ReturnKey;
  820.  
  821.         if(EscKey)
  822.             Handle->EscKey = EscKey;
  823.  
  824.         if(CursorKey)
  825.             Handle->CursorKey = CursorKey;
  826.  
  827.         if(TabKey)
  828.             Handle->TabKey = TabKey;
  829.  
  830.         if(ActiveString)
  831.             Handle->ActiveString = ActiveString;
  832.     }
  833. }
  834.